/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/container_impl.h"
#include "../data_struct/webapp.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "helper_webapp.h"
#include "app_plugin.h"

namespace cat
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    typedef xos_stl::xos_map< std::string, webapp::T > APP_MAP;
    typedef APP_MAP::iterator APP_ITER;

    typedef std::map< int, int > PORT_MAP;
    typedef PORT_MAP::iterator PORT_ITER;

    static APP_MAP * webapp_map_ptr = 0;
    static PORT_MAP * port_map_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    helper_webapp::helper_webapp()
    {
    }

    helper_webapp::~helper_webapp()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_webapp::scan_webapp_path()
    {
        int ret = 0;

        APP_MAP * pMap = webapp_map_ptr;
        char path[1024] = { 0 };
        xos::i_dir * pDir = 0;

        if( 0 == ret )
        {
            mgr::xos()->crt()->strcpy( path, sizeof( path ), mgr::xos()->exe_path() );
            mgr::xos()->misc()->path_append( path, config::get()->webapps.c_str() );
        }

        if( 0 == ret )
        {
            ret = mgr::xos()->xos()->create( xos::i_xos::XOS_OBJ_DIR, ( void** )&pDir );
        }

        if( 0 == ret )
        {
            ret = pDir->begin_find_file( path );
        }

        while( 0 == ret )
        {
            const char * lpszHost = 0;
            const char * pFind = 0;
            xos::i_file * pFile = 0;
            char web_path[4096];
            int nPort = 0;
            int r = pDir->get_find_result( &pFile );
            if( 0 != r )
            {
                break;
            }
            if( ( 0 == r ) && ( xos::i_file::FILE_TYPE_DIR != pFile->get_type() ) )
            {
                r = 1;
            }
            if( 0 == r )
            {
                lpszHost = pFile->get_name( 0, 0, 0 );
                pFind = mgr::xos()->crt()->strchr( lpszHost, '_' );
                if( !pFind )
                {
                    r = 1;
                }
            }
            if( 0 == r )
            {
                pFind++;
                nPort = mgr::xos()->crt()->atoi( pFind );
            }
            if( ( 0 == r ) && ( 0 == nPort ) )
            {
                ret = 1;
            }
            if( 0 == r )
            {
                mgr::xos()->crt()->strcpy( web_path, sizeof( web_path ), path );
                mgr::xos()->misc()->path_append( web_path, lpszHost );
            }
            if( 0 == r )
            {
                webapp::T * pW = webapp::get_item_from_pool( true );
                pW->init();
                pW->m_webapp_path = web_path;
                pW->m_host = lpszHost;
                pW->m_nPort = nPort;
                (*pMap)[pW->m_host] = pW;
            }
        }

        pDir->end_find_file();
        xos_stl::release_interface( pDir );

        return ret;
    }

    int helper_webapp::load_webapp_xml()
    {
        int ret = 0;

        APP_MAP * pMap = webapp_map_ptr;

        for( APP_ITER iter = pMap->begin(); ( 0 == ret ) && ( iter != pMap->end() ); )
        {
            xos_common::i_property * pConfigFile = 0;

            APP_ITER tmp_iter = iter++;
            webapp * pW = tmp_iter->second;

            if( 0 == ret )
            {
                char file[4096];
                mgr::xos()->crt()->strcpy( file, sizeof( file ), pW->m_webapp_path.c_str() );
                mgr::xos()->misc()->path_append( file, "web.xml" );
                ret = mgr::xos()->xml()->load_xml_file_to_property( file, ( xos::i_unknown** )&pConfigFile, 0 );
            }

            if( 0 == ret )
            {
                pW->m_pConfigProperty = pConfigFile;
                pConfigFile = 0;
            }
            
            if( 0 != ret )
            {
                LOG4( "load %s xml failed", pW->m_host.c_str() );
                pMap->erase( tmp_iter );
                xos_stl::release_interface( pW );
            }

            xos_stl::release_interface( pConfigFile );
        }

        return ret;
    }

    int helper_webapp::create_entrance()
    {
        int ret = 0;

        APP_MAP * pMap = webapp_map_ptr;

        for( APP_ITER iter = pMap->begin(); ( 0 == ret ) && ( iter != pMap->end() ); )
        {
            APP_ITER tmp_iter = iter++;
            webapp * pW = tmp_iter->second;
            int r = 0;
            if( 0 == r )
            {
                app_plugin obj( pW );
                r = obj.load( pW->m_webapp_path.c_str() );
            }
            if( 0 == r )
            {
                ( *port_map_ptr )[pW->m_nPort] = pW->m_nPort;
            }
            if( 0 != r )
            {
                LOG4( "load %s failed", pW->m_host.c_str() );
                xos_stl::release_interface( pW );
                pMap->erase( tmp_iter );
            }
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_webapp::scan_webapps()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = scan_webapp_path();
        }

        if( 0 == ret )
        {
            ret = load_webapp_xml();
        }

        if( 0 == ret )
        {
            ret = create_entrance();
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_webapp::init()
    {
        int ret = 0;
        if( 0 == ret )
        {
            xos_stl::init_map( webapp_map_ptr );
        }
        if( 0 == ret )
        {
            xos_stl::init_obj( port_map_ptr );
        }
        if( 0 == ret )
        {
            ret = scan_webapps();
        }
        return ret;
    }

    int helper_webapp::get_ports( int * pPortArray, int nNum, int * pnRetNum )
    {
        int ret = 0;
        int nIndex = 0;
        for( PORT_ITER iter = port_map_ptr->begin(); ( nIndex < nNum ) && ( iter != port_map_ptr->end() ); ++iter )
        {
            pPortArray[nIndex++] = iter->first;
        }
        if( pnRetNum )
        {
            *pnRetNum = nIndex;
        }
        return ret;
    }

    webapp * helper_webapp::find( const char * lpszHost )
    {
        APP_MAP * pMap = webapp_map_ptr;
        webapp * pRet = 0;
        if( !lpszHost )
        {
            return pRet;
        }
        APP_ITER iter = pMap->find( lpszHost );
        if( iter != pMap->end() )
        {
            pRet = iter->second;
        }
        return pRet;
    }

    int helper_webapp::term()
    {
        int ret = 0;
        xos_stl::term_map( webapp_map_ptr, true );
        xos_stl::term_obj( port_map_ptr );
        return ret;
    }

} // cat
